package com.liyu.iblog.dao.jpa;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.liyu.iblog.dao.BlogDao;
import com.liyu.iblog.domain.Blog;
import com.liyu.iblog.domain.Comment;
import com.liyu.iblog.domain.Tag;

@Repository("blogDao")
public class BlogDaoJpa extends GenericDaoJpa<Blog> implements BlogDao {

    private static final Logger logger = LoggerFactory.getLogger(BlogDaoJpa.class);
    
    public BlogDaoJpa() {
        super (Blog.class);
    }

    /**
     * to persist blog with the tag and category 
     * reference updated
     */
    @Override
    public void persistBlogConsistently(Blog blog) {
        
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public List<Blog> getBlogsWithTimeDescOrder(int firstIndex, int batchSize,Object fkey) {
        EntityManager em = emf.createEntityManager();
        List<Blog> blogs = null;
        try {
            Query query = em.createQuery(
                    "select b from Blog b " + 
                    "where b.userKey = :key order by b.createTime desc");
            query.setParameter("key", fkey);
            query.setFirstResult(firstIndex);
            query.setMaxResults(batchSize);
            blogs =  query.getResultList();
            blogs.size();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
        }
        return blogs;
    }

    @Override
    public Blog getBlogWithComments(Object key) {
        EntityManager em = emf.createEntityManager();
        Blog blog = null;
        try {
            blog = em.find(Blog.class, key);
            if(blog == null)
                return null;
            List<Comment> comments = blog.getComments();
            logger.debug("comment size of blog <" + key  + "> is " + comments.size());
            /* force the lazy loading collection to be loaded, 
             * populate the encoded key if the comment doesn't have one
             */
            for (Comment c : comments)
                if (c.getEncodedKey() == null)
                    c.setEncodedKey(KeyFactory.keyToString(c.getKey()));
            
            //check if the blog comment count equals the actual commnet number
            if (blog.getCommentCount() != comments.size()) 
                blog.setCommentCount(comments.size());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
        }
        return blog;
    }

    
    @SuppressWarnings("unchecked")
    @Override
    public List<Blog> getBlogsByCategory(Object categoryId, int firstIndex,
            int batchSize) {
        EntityManager em = emf.createEntityManager();
        List<Blog> blogs = new ArrayList<Blog>();
        try {
            // this will automatically build index on categoryKey on app engine
            Query query = em.createQuery(
                    "select b from Blog b " + 
                    "where b.categoryKey = :key order by b.createTime desc");
            query.setParameter("key", categoryId);
            query.setFirstResult(firstIndex);
            query.setMaxResults(batchSize);
            blogs =  query.getResultList();
            blogs.size();
            /*
            Category category = em.find(Category.class, categoryId);
            if (category == null)
                return null;
            List<Key> blogKeyList = category.getBlogKeys();
            if (blogKeyList.size() == 0)
                return null;
            int startIndex = blogKeyList.size() - firstIndex - 1;
            if (startIndex < 0)
                return null;
            Blog b = null;
            for (int i = startIndex, cnt = 0; i >= 0 && cnt < batchSize; i--, cnt++) {
                b = em.find(Blog.class, blogKeyList.get(i));
                blogs.add(b);
            }
            */
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
        }
        return blogs;
    }

    //the key lasted blog located at the end of the list
    @Override
    public List<Blog> getBlogByTag(String tagId, int firstIndex, int batchSize) {
        EntityManager em = emf.createEntityManager();
        List<Blog> blogs = new ArrayList<Blog>();
        try {
            Tag tag = em.find(Tag.class, tagId);
            if (tag == null)
                return null;
            List<Key> blogKeyList = tag.getBlogKeys();
            if (blogKeyList.size() == 0)
                return null;
            int startIndex = blogKeyList.size() - firstIndex - 1;
            //reach the end
            if (startIndex < 0)
                return null;
            Blog b = null;
            for (int i = startIndex, cnt = 0; i >= 0 && cnt < batchSize; i--, cnt++) {
                b = em.find(Blog.class, blogKeyList.get(i));
                blogs.add(b);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            em.close();
        }
        return blogs;
    }  
    
}